﻿using System;
using System.IO;
using System.Drawing;
using System.Drawing.Text;
using iTextSharp.text.pdf;

namespace Dosimetria.Shared
{
    public class CodeBarService
    {

        public static byte[] GenerarCodigoEAN13(string codigo)
        {
                
            string _code = encodeENA13(codigo);

            BarcodeEAN barCode = new BarcodeEAN();
            barCode.StartStopText = true;
            barCode.GenerateChecksum = true;
            barCode.ChecksumText = true;
            
            barCode.Code = encodeENA13(codigo);

            Bitmap bm = new Bitmap(barCode.CreateDrawingImage(System.Drawing.Color.Black, System.Drawing.Color.White));

            int xOffset = 10;
            Image bmt = new Bitmap(bm.Width + xOffset, bm.Height + 14);

            Graphics g = Graphics.FromImage(bmt);

            g.FillRectangle(new SolidBrush(Color.White),0,0, bm.Width + xOffset, bm.Height + 14);
           
            Font drawFont = new Font("Arial", 8);
            SolidBrush drawBrush = new SolidBrush(Color.Black);
            SizeF stringSize;

            stringSize = g.MeasureString(_code, drawFont);

            Single xCenter = (bm.Width - stringSize.Width) /2;
            Single x = xCenter;
            Single y = bm.Height;

            StringFormat drawFormat = new StringFormat();
            drawFormat.FormatFlags = StringFormatFlags.NoWrap;

            g.DrawImage(bm, xOffset, 0);
            
            if ( xOffset < 10 )
            {
                g.DrawString(_code.Substring(0,1), drawFont, drawBrush, 0, y, drawFormat);
            }
            else
            {
                g.DrawString(_code.Substring(0,1), drawFont, drawBrush, xOffset - 10, y, drawFormat);
            }

            Single x1 = xOffset + 4;
            g.DrawString(_code.Substring(1,6), drawFont, drawBrush, x1, y, drawFormat);
            
            Single x2 = xOffset + 50;
            g.DrawString(_code.Substring(7, 6), drawFont, drawBrush, x2, y, drawFormat);
            g.DrawLine(Pens.Black, xOffset + 0, 0, xOffset + 0, bm.Height + 8);
            g.DrawLine(Pens.Black, xOffset + 2, 0, xOffset + 2, bm.Height + 8);
            g.DrawLine(Pens.Black, xOffset + 46, 0, xOffset + 46, bm.Height + 8);
            g.DrawLine(Pens.Black, xOffset + 48, 0, xOffset + 48, bm.Height + 8);
            g.DrawLine(Pens.Black, xOffset + 92, 0, xOffset + 92, bm.Height + 8);
            g.DrawLine(Pens.Black, xOffset + 94, 0, xOffset + 94, bm.Height + 8);


            //Convierto a byte[]
            ImageConverter converter = new ImageConverter();
            return (byte[])converter.ConvertTo(bmt, typeof(byte[]));
        }


        /// <summary>
        /// Metodo que toma un codigo y lo transforma en la cadena ENA13 sin digito de control (12 caracteres)
        /// el formato utilizado es AAABCCCCCCCCD
        /// Donde:
        /// AAA: Representacion pais (780 Chile)
        /// B: Identificación empresa  (en nuestro caso utilizaremos el 1 como dummie
        /// CCCCCCCC: Digitos correspondiente al codigo del dosimetro en caso de no llenar los 8 caracteres se completaran con 0 al final
        /// D: Digito de control el cual se calcula en funciones de los digitos anteriores
        /// </summary>
        /// <param name="codigo">codigo de dosimetro</param>
        /// <returns>Codigo dosimetro preparado para ser impreso en un codigo de barras similar a la especificacion EAN</returns>
        private static string encodeENA13(string codigo)
        {
            string aux = "7801";
            aux += codigo;

            while (aux.Length < 12)
            {
                aux += "0";
            }

            return digitoControlENA13(aux);
        }

        /// <summary>
        /// Metodo que toma el codigo ENA13 de 12 digitos y genera su digito de control
        /// Para obtener el digito de control se sigue la siguiente especificacion
        /// Se numeran los dígitos de derecha a izquierda. (invertir los numeros)
        /// A continuación se suman los dígitos de las posiciones impares, el resultado se multiplica por 3, y se le suman los dígitos de las posiciones pares. 
        /// Se busca decena inmediatamente superior y se le resta el resultado obtenido. 
        /// El resultado final es el dígito de control. 
        /// Si el resultado es múltiplo de 10 el dígito de control será 0.
        /// </summary>
        /// <param name="cod"></param>
        /// <returns></returns>
        private static string digitoControlENA13(string cod)
        {
            try
            {
                char[] _codArray = cod.ToCharArray();
                string _codInvertido = "";
                //Realizo la inversion del codigo 
                for(int i = _codArray.Length - 1; i >= 0; i--)
                {
                    _codInvertido += _codArray[i];
                }

                //Paso nuevamente a array el codigo ya invertido
                _codArray = _codInvertido.ToCharArray();

                int sumaDigImpar = 0;
                int sumaDigPar = 0;
                //Sumo las posiciones impares e impares
                for(int i = 0; i < _codArray.Length; i++)
                {
                    if((i + 1) % 2 == 0)
                    {
                        sumaDigPar += Convert.ToInt32("" + _codArray[i]);
                    }
                    else
                    {
                        sumaDigImpar += Convert.ToInt32("" + _codArray[i]);
                    }
                }

                //Multiplico el resultado de la suma de las posiciones impares por 3 y le adiciono la suma de las posiciones pares
                int resOperacion = (sumaDigImpar * 3) + sumaDigPar;
                int _digControl = getDigitoControl(resOperacion);

                cod += _digControl.ToString();

            }catch(Exception e)
            {
                
            }
            return cod;
        }

        private static int getDigitoControl(int x)
        {
            int _aux = x % 10;
            int _digControl;

            if (_aux != 0)
            {
                _digControl = (((x / 10) * 10) + 10) - x;
            }
            else
            {
                _digControl = 0;
            }
            return _digControl;
        }

        public static byte[] GenerarCodigo(string code, int width, int height, int size)
        {
            var resultado = new byte[] { };
            width = (width == 0) ? 200 : width;
            height = (width == 0) ? 60 : height;
            size = (width == 0) ? 60 : size;

            if (!string.IsNullOrEmpty(code))
            {
                using (var stream = new MemoryStream())
                {
                    var bitmap = new Bitmap(width, height);
                    var grafic = Graphics.FromImage(bitmap);
                   // var fuente = CargarFuente("FRE3OF9X.TTF", size);
                    var fuente = CargarFuente("BARCOD39.TTF", size);
                    var point = new Point();
                    var brush = new SolidBrush(Color.Black);

                    grafic.FillRectangle(new SolidBrush(Color.White), 0, 0, width, height);
                    grafic.DrawString(FormatBarCode(code.ToUpper()), fuente, brush, point);
                    bitmap.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg);
                    stream.Seek(0, SeekOrigin.Begin);
                    resultado = stream.ToArray();
                }
            }

            return resultado;
        }


        /// <summary>
        /// Formato con los caracteres de escape establecidos en la fuente que utilizamos.
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
        private static string FormatBarCode(string code)
        {
            return string.Format("*{0}*", code);
        }
        /// <summary>
        /// Generamos la nueva fuente para cargar en la imagen
        /// </summary>
        /// <param name="fuente"></param>
        /// <param name="size"></param>
        /// <returns></returns>
        private static Font CargarFuente(string fuente, int size)
        {
            var pfc = new PrivateFontCollection();
            //var f = "FRE3OF9X.TTF";
            var f = "BARCOD39.TTF";
            //switch (fuente)
            //{
            //    case "E39":
            //        f = "BARCOD39.TTF";
            //        break;
            //    case "E13":
            //        f = "EAN-13.TTF";
            //        break;
            //    case "E9":
            //        f = "FRE3OF9X.TTF";
            //        break;
            //}

            pfc.AddFontFile(System.Configuration.ConfigurationManager.AppSettings.Get("PATH_FONTS") + @"\" + f);
            return new Font(pfc.Families[0], size);
        }


        ///// <summary>rna la lista de fuentes disponibles para generar los códigos de Barras
        ///// </summary>
        ///// <returns></returns>
        //public static List<Fuente> GetDatos()
        //{
        //    return new List<Fuente>()
        //                  {

        //                      new Fuente(){Id = "E39", Nombre = "BARCOD39", Fichero = "BARCOD39.TTF"},
        //                      new Fuente(){Id = "E13",Nombre = "EAN-13", Fichero = "EAN-13.TTF"},
        //                      new Fuente(){Id = "E9", Nombre = "FRE3OF9X", Fichero = "FRE3OF9X.TTF"},
        //                  };

        //}


    }
}